package com.smartcommunity.service.sixEntity.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.smartcommunity.base.common.CacheMap;
import com.smartcommunity.bean.constant.Constant;
import com.smartcommunity.bean.entity.Village;
import com.smartcommunity.bean.model.Pager;
import com.smartcommunity.bean.model.Result;
import com.smartcommunity.dao.sixEntity.SixEntityDao;
import com.smartcommunity.dao.village.VillageDao;
import com.smartcommunity.entity.sixEnity.DataTypeStatistic;
import com.smartcommunity.entity.village.SixEntity;
import com.smartcommunity.entity.village.SixStatisticsEntity;
import com.smartcommunity.es.common.EsBasedataEnum;
import com.smartcommunity.es.common.EsIndex;
import com.smartcommunity.es.common.EsRestUtils;
import com.smartcommunity.service.sixEntity.SixEntityService;
import com.smartcommunity.utils.ExecutorUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.concurrent.Future;


@Slf4j
@Service
public class SixEntityServiceImpl implements SixEntityService {
    private final SixEntityDao sixEntityDao;

    private final VillageDao villageDao;

    @Autowired
    private EsRestUtils esRestUtils;

    @Autowired
    public SixEntityServiceImpl(SixEntityDao sixEntityDao, VillageDao villageDao) {
        this.sixEntityDao = sixEntityDao;
        this.villageDao = villageDao;
    }

    /**
     * 批量入库对应小区一标六实数据
     * @param sixEntityList 小区一标六实数据列表
     */
    @Override
    public void addSixEntities(List<SixEntity> sixEntityList) {
        sixEntityDao.addSixEntities(sixEntityList);
    }

    @Override
    @Transactional
    public void batchAddSixEntities(List<SixEntity> sixEntityList) {
        sixEntityDao.deleteAllSixEntity();
        sixEntityDao.addSixEntities(sixEntityList);
    }

    /**
     * 入库单个小区一标六实数据，若存在则更新
     * @param sixEntity 小区一标六实数据
     */
    @Override
    public void addOrUpdateSixEntity(SixEntity sixEntity) {
        sixEntityDao.addOrUpdateSixEntity(sixEntity);
    }

    /**
     * 获取一标六实记录总数
     * @return 记录总数
     */
    @Override
    public Integer getSixEntityCount() {
        return sixEntityDao.getSixEntityCount();
    }

    /**
     * 根据小区编号(多选时逗号分隔)和小区名称查询关联的小区一标六实数据
     *
     * @param map 参数，villageCode/villageName
     * @return 小区六实数据列表
     * @author TianZongBing
     * @date 2020/02/22
     */
    @Override
    public Result listSixEntityByVillage(Map<String, Object> map) {
        JSONObject param = new JSONObject(map);
        // 分页必须,只对后面一个查询有效
        Integer pageNumber = param.getInteger("pageNumber");
        Integer pageSize = param.getInteger("pageSize");
        PageHelper.startPage(pageNumber, pageSize);

        //获取小区列表
        List<Village> villageList = villageDao.getVillageList(map);
        int count = (int) ((Page) villageList).getTotal();
        Pager page = new Pager(pageNumber, pageSize, count);

        List<SixStatisticsEntity> entityList = sixEntityDao.getSixEntitySumGroupByVillageCode(param);

        //遍历小区数据
        Map<String,SixEntity> sixMap = new HashMap<>();
        List<SixEntity> sixEntityList = new ArrayList<>();
        for(Village village :villageList){
            SixEntity sixEntity = new SixEntity();
            sixEntity.setVillageCode(village.getVillageCode());
            sixEntity.setVillageName(village.getVillageName());
            sixEntity.setParentId(village.getParentId());
            sixEntity.setOrgName(village.getParentName());
            sixEntity.setPicUrl(village.getPicUrl());
            sixEntity.setAddress(village.getAddress());
            sixMap.put(village.getVillageCode(),sixEntity);
        }

        //封装统计数据
        for (SixStatisticsEntity statisticsEntity :entityList) {
            String vCode = statisticsEntity.getVillageCode();//小区编码
            String type = statisticsEntity.getType();//数据类型
            int ct = statisticsEntity.getCount();//统计数量
            if(sixMap.containsKey(vCode)){
                if(Constant.PEOPLETYPE.equals(type)){
                    sixMap.get(vCode).setPeopleCount(ct);
                }else if(Constant.HOUSETYPE.equals(type)){
                    sixMap.get(vCode).setHouseCount(ct);
                }else if(Constant.BUILDTYPE.equals(type)){
                    sixMap.get(vCode).setBuildingCount(ct);
                }else if(Constant.DEVICESTYPE.equals(type)){
                    sixMap.get(vCode).setSecurityEquipmentCount(ct);
                }else if(Constant.REALPOWER.equals(type)){
                    sixMap.get(vCode).setPowerCount(ct);
                }else if(Constant.COMPANYTYPE.equals(type)){
                    sixMap.get(vCode).setCompanyCount(ct);
                }else if(Constant.VEHICLETYPE.equals(type)){
                    sixMap.get(vCode).setVehicleCount(ct);
                }
            }
        }

        for(Village village :villageList){
            SixEntity sixEntity = sixMap.get(village.getVillageCode());
            sixEntityList.add(sixEntity);
        }
        page.setList(sixEntityList);

        return Result.ok(page);
    }

    @Override
    public Result listNowSixEntityByVillage(Map<String, Object> map) {
        JSONObject param = new JSONObject(map);
        // 分页必须,只对后面一个查询有效
        Integer pageNumber = param.getInteger("pageNumber");
        Integer pageSize = param.getInteger("pageSize");
        PageHelper.startPage(pageNumber, pageSize);
        List<SixEntity> entityList = sixEntityDao.selectNowByVillageCodeName(param);
        int count = (int) ((Page) entityList).getTotal();
        Pager page = new Pager(pageNumber, pageSize, count);
        page.setList(entityList);
        return Result.ok(page);
    }
    /**
     * 获取一标六实统计总数
     * @param map
     * @return
     */
    public Result getSixEntitySumByVillageCode(Map<String, Object> map) {
        SixEntity sixEntity = sixEntityDao.getSixEntitySumByVillageCode(map);
        return Result.ok(sixEntity);
    }

    /**
     * 实时获取一标六实统计总数
     * @param map
     * @return
     */
    public Result getNowSixEntitySumByVillageCode(Map<String, Object> map) {
        SixEntity sixEntity = sixEntityDao.getNowSixEntitySumByVillageCode(map);
        return Result.ok(sixEntity);
    }

    public Result getSixEntitySum(Map<String, Object> map) {
        SixEntity sixEntity = new SixEntity();
        //获取一标六实统计数量
        List<SixStatisticsEntity> sixEntityList = sixEntityDao.getSixEntitySum(map);
        for (SixStatisticsEntity six :sixEntityList){
            String type = six.getType();
            int count = six.getCount();
            if(Constant.PEOPLETYPE.equals(type)){
                sixEntity.setPeopleCount(count);
            }else if(Constant.VEHICLETYPE.equals(type)){
                sixEntity.setVehicleCount(count);
            }else if(Constant.HOUSETYPE.equals(type)){
                sixEntity.setHouseCount(count);
            }else if(Constant.REALPOWER.equals(type)){
                sixEntity.setPowerCount(count);
            }else if(Constant.DEVICESTYPE.equals(type)){
                sixEntity.setSecurityEquipmentCount(count);
            }else if(Constant.COMPANYTYPE.equals(type)){
                sixEntity.setCompanyCount(count);
            }
        }

        String villageCode = map.get("villageCode")==null?"":map.get("villageCode").toString();
        List<String> userVillageCode = Arrays.asList(villageCode.replaceAll("'", "").split(","));

        //由于一人多房问题，人员数量从es统计
        sixEntity.setPeopleCount(getPeopleCount(userVillageCode));

        //由于一人多房问题，车辆数量从es统计
        sixEntity.setVehicleCount(getVehicleCount(userVillageCode));

        //获取小区数量
        sixEntity.setVillageCount(villageDao.getVillageCountByCode(map));
        return Result.ok(sixEntity);
    }


    public Integer getVehicleCount(List<String> userVillageCode){
        String[] indexs = new String[]{EsIndex.BASEDATA};
        //车辆数量从es统计
        BoolQueryBuilder vehicleTotalQueryBuilder = buildCountQueryBuilder(userVillageCode, EsBasedataEnum.VEHICLE.getIntValue());
        Future<Long> vehicleTotalFuture = ExecutorUtil.executorService.submit(() -> esRestUtils.getTotalRecords(indexs, vehicleTotalQueryBuilder));
        try {
            return vehicleTotalFuture.get().intValue();
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    public Integer getPeopleCount(List<String> userVillageCode){
        String[] indexs = new String[]{EsIndex.BASEDATA};
        //人员数量从es统计
        BoolQueryBuilder peopleTotalQueryBuilder = buildCountQueryBuilder(userVillageCode, EsBasedataEnum.PEOPLE.getIntValue());
        Future<Long> peopleTotalFuture = ExecutorUtil.executorService.submit(() -> esRestUtils.getTotalRecords(indexs, peopleTotalQueryBuilder));
        try {
            return peopleTotalFuture.get().intValue();
        } catch (Exception e) {
            e.printStackTrace();
            return  0;
        }
    }

    /**
     * 获取设备数量统计
     * @param map
     * @return
     */
    public Result getDeviceSum(Map<String, Object> map) {

        //初始化数据
        Map<Integer,DataTypeStatistic> initMap = new HashMap<>();
        for (Map.Entry<Integer, String> entry : CacheMap.DEVICE_TYPE_MAP.entrySet()) {
            //类型值
            Integer value = Integer.parseInt(entry.getKey()+"");
            //页面设计只显示视频监控、车辆卡口、人脸卡口、门禁设备四种类型
            if(Constant.CAMERATYPE_VALUE==value ||Constant.VEHICLETYPE_VALUE ==value ||
                    Constant.FACETYPE_VALUE == value || Constant.ACCESSTYPE_VALUE == value ){
                DataTypeStatistic dataTypeStatistic = new DataTypeStatistic();
                //类型名称
                dataTypeStatistic.setName(entry.getValue());
                dataTypeStatistic.setValue(value);
                initMap.put(value,dataTypeStatistic);
            }
        }
        //获取一标六实统计数量
        List<SixStatisticsEntity> sixList = sixEntityDao.getCountByChildType(map);

        for(SixStatisticsEntity six : sixList){
            int type = six.getChildType();
            int count = six.getCount();
            DataTypeStatistic dataTypeStatistic = initMap.get(type);
            if(dataTypeStatistic==null){
                continue;
            }
            dataTypeStatistic.setNum(count);
        }
        List<DataTypeStatistic> list = new ArrayList<>();
        for (Integer key : initMap.keySet()) {
            list.add(initMap.get(key));
        }
        return Result.ok(list);
    }


    /**
     * 构造小区参数
     * @param queryBuilder
     */
    private void buildVillageCodeParam(BoolQueryBuilder queryBuilder, List<String> villageCode) {
        if(CollectionUtils.isNotEmpty(villageCode)) {
            queryBuilder.must(QueryBuilders.termsQuery("villageCode", villageCode));
        }
    }

    /**
     * 构造es查询总数的参数
     * @param villageCode
     * @param dataType
     * @return
     */
    private BoolQueryBuilder buildCountQueryBuilder(List<String> villageCode, int dataType){
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        buildVillageCodeParam(queryBuilder, villageCode);
        queryBuilder.must(QueryBuilders.matchPhraseQuery("dataType", dataType));
        return queryBuilder;
    }
}
